package models

import (
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"gitchina/kly_service/data"
	"gitchina/kly_service/errors"
	"gitchina/kly_service/util"
	_ "github.com/astaxie/beego/orm"
	"regexp"
	"strings"
)

var device_salt = `*(#_@2MFI`
var dict_map = make(map[string]map[string]string)
var para_map = make(map[string]string)

type Ad struct {
	PicUrl  string `json:"pic_url"`
	HtmlUr  string `json:"html_url"`
	SortNum int    `json:"sort_num"`
}

type DeviceInfo struct {
	Id    string `json:"id"`
	OS    string `json:"os"`
	Model string `json:"model"`
}

type ClientErrorLog struct {
	OS   string `json:"os"`
	UA   string `json:"ua"`
	Type string `json:"type"`
	Code string `json:"code"`
	Url  string `json:"url"`
	Info string `json:"info"`
	Time string `json:"time"`
}

type ClientVersion struct {
	MinVersion     string `json:"min_ver"`
	CurrentVersion string `json:"curr_ver"`
}

type General struct{}

var ad_list []Ad
var clientVer ClientVersion

func GeneralInit() {
	var code_name_map map[string]string
	var repo data.GeneralRepo
	for _, list := range repo.GetDicts() {
		parentId := list[2].(string)
		if parentId != "" {
			if _, ok := dict_map[parentId]; !ok {
				code_name_map = make(map[string]string)
				dict_map[parentId] = code_name_map
			}
			code_name_map[list[1].(string)] = list[0].(string)
		}
	}

	for _, list := range repo.GetParas() {
		para_map[list[0].(string)] = list[1].(string)
	}

	loadAdList()
	loadClientVersion()
}

func (g General) GetDict(parentId string) map[string]string {
	c, _ := dict_map[parentId]
	return c
}

func (g General) GetPara(key string) string {
	c := para_map[key]
	return c
}

func (g General) GetAdList() []Ad {
	if len(ad_list) == 0 {
		loadAdList()
	}
	return ad_list
}

func (g General) GetClientId(device DeviceInfo, profile string) (clientId string, err error) {
	var repo data.GeneralRepo
	if len(device.Id) != 0 {
		clientId = fmt.Sprintf("1%x", sha1.Sum([]byte(fmt.Sprintf("%s%s", device.Id, device_salt))))
		if err = repo.AddClientId(clientId, profile); err != nil {
			util.GetLogger().Error("[model-GetClientId] - error:%s", err.Error())
		}
	}
	return
}

func (g General) AddClientErrorLog(errorLogs string) {
	//format : os|ua|type|code|url|info|time\n
	var repo data.GeneralRepo
	split := strings.Split(errorLogs, "\n")
	logList := make([]data.ClientLogDto, len(split))
	for i, log := range split {
		logList[i] = data.ClientLogDto{
			Name:     "Client",
			Message:  log,
			ServerIp: "::1",
		}
		sepIdx := strings.LastIndex(log, "|")
		if sepIdx != -1 && sepIdx+1 < len(log) {
			logList[i].Time = log[sepIdx+1 : len(log)]
		}
	}
	if err := repo.AddClientErrorLogs(logList); err != nil {
		util.GetLogger().Error("[model-AddClientErrorLog] - error:%s", err.Error())
	}
}

func (g General) CheckVersion(ver string) (err error) {
	var ok bool
	if ok, _ = regexp.Match(`^\d+\.\d+\.\d+$`, []byte(ver)); ok {
		fmt.Println(strings.Compare(ver, clientVer.CurrentVersion))
		if ok = strings.Compare(ver, clientVer.CurrentVersion) > 0; ok {
			err = errors.New(errors.MSG_General_Invalid_Or_Low_Ver)
		} else {
			if ok = strings.Compare(ver, clientVer.MinVersion) >= 0; !ok {
				err = errors.New(errors.MSG_General_Invalid_Or_Low_Ver)
			}
		}
	} else {
		err = errors.New(errors.MSG_General_Invalid_Ver)
	}
	return
}

func loadAdList() {
	var repo data.GeneralRepo
	list := repo.GetAds(6)
	ad_list = make([]Ad, len(list))
	for idx, item := range list {
		ad_list[idx] = Ad{PicUrl: item.PicUrl, HtmlUr: item.HtmlUrl, SortNum: item.SortNum}
	}
}

func loadClientVersion() {
	if v, ok := para_map["version"]; ok {
		json.Unmarshal([]byte(v), &clientVer)
	}
}
